/*************************************************************************
	> File Name: server.c
	> Author: 李远远
	> Mail: 
	> Created Time: 2018年08月27日 星期一 12时18分08秒
 ************************************************************************/

#include <server.h>

/*
 * 函数名:init
 * 功能:初始化服务器数据
	//初始化个线程管道,读取配置信息
 * 参数:无,
 * 返回值:无
 */
void init()
{
	create_fifo(SOCKET_FIFO);
	create_fifo(SQLITE_FIFO);
	create_fifo(TOWARD_M0_FIFO);
	create_fifo(COLLECT_DATA_FIFO);
	
	collect_init("/dev/ttyUSB0");
	FILE * c;

	if (NULL == (c = fopen(CONFIG_DATA, "r")))
	{
		config *con = (config *)malloc(sizeof(config));
		con->max_env.tem = 30;
		con->max_env.hum = 40;
		con->max_env.lux = 120;
		
		con->min_env.tem = 25;
		con->min_env.hum = 30;
		con->min_env.lux = 70;
		write_config_data(con);
		free(con);
	}
	else
	{
		fclose(c);
	}
	printf("chu shi hua wan cheng\n");
}


/*
 * 函数名:socket_pthread
 * 功能:socket线程函数
	//创建socket并监听,接收客户端连接,接收客户端发送的消息,对消息进行不同的处理
	接收:从客户端接收
		1.登录信息					标识：#ADMI#	通过数据库接收消息管道,发送给数据库操作线程
		2.设备控制信息				标识：#DEVI#	通过向M0板发送消息管道,发送给向M0板发送消息线程
		3.修改配置信息				标识：#PZXG#	通过数据库接收消息管道,发送给数据库操作线程,通过采集消息线程管道发送给采集消息线程,
		4.查询历史信息				标识：#CXLS#	通过数据库接收消息管道,发送给数据库操作线程
		5.如果登录成功				标识：#DLCG#	通过采集消息线程管道,把客户端登录状态信息发送给采集消息线程
	发送:向客户端发送
		1.客户端与服务器通信的结构体	标识：#ZTXX#
		2.配置信息结构体				标识：#PZXX#
		3.登录信息返回结果				标识：#ADMR#
		4.历史数据						标识：#LSSJ#
 * 参数:void *,
 * 返回值:void *
 */
void *socket_pthread(void *s)
{
	int ret = 0;
	int socketID;
	int newID = 0;
	int addrLength = 0;
	struct sockaddr_in addr;
	
	pthread_t p1;
	
	//创建socket
	if ((socketID = socket_init(58888)) == -1)
	{
		perror("socket**********socket_init error");
		return (void *)ERR;
	}
	
    printf("socket**********kai shi jian ting\n");
	while(1)
	{
		newID = accept(socketID, (struct sockaddr *)&addr, &addrLength);
		if (0 < newID)
		{
			printf("socket**********ke hu duan lian jie cheng gong:%d\n", newID);
			pthread_create(&p1, NULL, socket_read_pthread, &newID);
		}
	}
	printf("socket**********socket guan bi\n");
	close(socketID);
	return 0;
}


/*
 * 函数名:sqlite_pthread
 * 功能:数据库操作线程函数
	//通过读取管道信息,操作数据库
	从管道读取的信息:
		1.保存采集消息线程发送过来的实时数据	标识：#ZTXX#	数据库插入数据
		2.登录信息								标识：#ADMI#	数据库查询,查询结果通过socket线程管道发送给socket线程	
		3.查询历史信息							标识：#CXLS#	查询数据库,查询结果通过socket线程管道发送给socket线程	
		4.修改配置信息							标识：#PZXG#	修改数据库配置信息
	从管道发送出去的信息:
		1.登录信息返回结果						标识：#ADMR#	查询结果通过socket线程管道发送给socket线程
		2.查询历史信息反馈						标识：#LSSJ#	查询结果通过socket线程管道发送给socket线程
 * 参数:void *,
 * 返回值:void *
 */
void *sqlite_pthread(void *s)
{
	//以只读方式打开管道
	int fifo_fd = open(SQLITE_FIFO, O_RDWR);
	if (-1 == fifo_fd)
	{
		perror("open TOWARD_M0_FIFO error");
		return (void *)ERR;
	}
	
	use_mysql();
	insert_default_user_password_table();
	
	while(1)
	{
		sqlite_read_fifo(fifo_fd);
	}
	close(fifo_fd);
}


/*
 * 函数名:toward_M0_pthread
 * 功能:向M0板发送消息线程线程函数
	//通过管道读取信息
		设备控制信息		标识：#DEVI#	把该信息发送给M0板
 * 参数:void *,
 * 返回值:void *
 */
void *toward_M0_pthread(void *s)
{
	//以只读方式打开管道
	int fifo_fd = open(TOWARD_M0_FIFO, O_RDWR);
	if (-1 == fifo_fd)
	{
		perror("open TOWARD_M0_FIFO error");
		return (void *)ERR;
	}
	//printf("TOWARD_M0_FIFO管道打开成功:%d\t%s\n", fifo_fd, TOWARD_M0_FIFO);
	
	while(1)
	{
		toward_M0(fifo_fd);
	}
	close(fifo_fd);
}


/*
 * 函数名:collect
 * 功能:采集M0板数据并处理的函数
	//从M0板采集数据,并进行处理
	从管道接收的信息:
		1.客户端登录状态和客户端登录socketID		标识：#DEVI#
	从M0板采集数据:
		1.数据的采集
		2.数据的初步处理,比如超级10次求平均值
		3.数据的处理,环境数据是否超标,环境是否改变,设备状态是否需要改变
		4.实时数据的保存,通过数据库操作线程管道,把实时数据发送给数据库		标识：#ZTXX#
		5.如果用户登录,向客户端发送实时数据信息								标识：#ZTXX#
 * 参数:无
 * 返回值:无
 */
void collect()
{
	
	int ret = 0;
	adm_state *adm_s = (adm_state *)malloc(sizeof(adm_state));
	server_to_client *stc = (server_to_client *)malloc(sizeof(server_to_client));
	config *con = (config *)malloc(sizeof(config));
	memset(stc, 0, sizeof(server_to_client));
	memset(con, 0, sizeof(config));
	memset(adm_s, 0, sizeof(adm_state));
	//读取配置信息
	read_config(con);
	
	//以只读,非阻塞方式打开管道
	int fifo_fd = open(COLLECT_DATA_FIFO, O_RDWR | O_NDELAY);
	if (0 > fifo_fd)
	{
		perror("open COLLECT_DATA_FIFO error");
		return ;
	}
	//printf("COLLECT_DATA_FIFO管道打开成功:%d\t%s\n", fifo_fd, COLLECT_DATA_FIFO);
	//printf("max_tem=%f\tmax_hum=%f\tmax_lux=%f\n", con->max_env.tem, con->max_env.hum, con->max_env.lux);
	//printf("min_tem=%f\tmin_hum=%f\tmin_lux=%f\n", con->min_env.tem, con->min_env.hum, con->min_env.lux);
    while(1)
    {
//printf("11max_tem=%f\tmax_hum=%f\tmax_lux=%f\n", con->max_env.tem, con->max_env.hum, con->max_env.lux);
//printf("11min_tem=%f\tmin_hum=%f\tmin_lux=%f\n", con->min_env.tem, con->min_env.hum, con->min_env.lux);
		memset(stc, 0, sizeof(server_to_client));
        //数据的采集与处理
		ret = data_dispose(stc, adm_s, fifo_fd, con);
//printf("22max_tem=%f\tmax_hum=%f\tmax_lux=%f\n", con->max_env.tem, con->max_env.hum, con->max_env.lux);
//printf("22min_tem=%f\tmin_hum=%f\tmin_lux=%f\n", con->min_env.tem, con->min_env.hum, con->min_env.lux);
		//数据判断
		ret = data_judge(stc, con);
//printf("33max_tem=%f\tmax_hum=%f\tmax_lux=%f\n", con->max_env.tem, con->max_env.hum, con->max_env.lux);
//printf("33min_tem=%f\tmin_hum=%f\tmin_lux=%f\n", con->min_env.tem, con->min_env.hum, con->min_env.lux);
		//获取当前时间
		get_now_time(&stc->nowtime);
//printf("44max_tem=%f\tmax_hum=%f\tmax_lux=%f\n", con->max_env.tem, con->max_env.hum, con->max_env.lux);
//printf("44min_tem=%f\tmin_hum=%f\tmin_lux=%f\n", con->min_env.tem, con->min_env.hum, con->min_env.lux);
		//向数据库操作进程发送数据
		ret = write_sql_data(stc);
//printf("55max_tem=%f\tmax_hum=%f\tmax_lux=%f\n", con->max_env.tem, con->max_env.hum, con->max_env.lux);
//printf("55min_tem=%f\tmin_hum=%f\tmin_lux=%f\n", con->min_env.tem, con->min_env.hum, con->min_env.lux);		
		if (1 == adm_s->state)
		{
			//向客户端发送数据
			ret = write_cli_data(stc, adm_s);
		}
//printf("66max_tem=%f\tmax_hum=%f\tmax_lux=%f\n", con->max_env.tem, con->max_env.hum, con->max_env.lux);
//printf("66min_tem=%f\tmin_hum=%f\tmin_lux=%f\n", con->min_env.tem, con->min_env.hum, con->min_env.lux);
		//sleep(1);
    }
	
}


/*
 * 函数名:close_server
 * 功能:关闭服务器
 * 参数:无
 * 返回值:无
 */
void close_server()
{
	
}

/*
 * 函数名:fifo_write
 * 功能:通过管道发送数据
 * 参数:	int fifo_fd:管道打开的文件标识符
			int socketID:客户端连接的socketID,无客户端连接填写0
			void *data:要发送的数据
 * 返回值:无
 */
int fifo_write(int fifo_fd, int socketID, void *data)
{
	
}

